package com.jplus.core.bean;

import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.core.AppConstant;
import com.jplus.core.InstanceFactory;
import com.jplus.core.bean.annotation.Component;
import com.jplus.core.util.FormatUtil;
import com.jplus.core.util.SecurityUtil;

/**
 * 初始化所有bean实例<br>
 * bean容器管理
 * 
 * @author Yuanqy
 *
 */
public class BeanHandle {
    private static final Logger logger = LoggerFactory.getLogger(BeanHandle.class);
    private static String encName = "SHA-256";
    /**
     * 所有组件类[未实例]
     */
    public static Set<Class<?>> beanSet = new HashSet<Class<?>>();

    /**
     * 环绕组件[init/destroy][未实例]
     */
    public static final TreeSet<Class<?>> beanAround = new TreeSet<Class<?>>(new Comparator<Class<?>>() {
	@Override
	public int compare(Class<?> o1, Class<?> o2) {
	    Component c1 = o1.getAnnotation(Component.class);
	    Component c2 = o1.getAnnotation(Component.class);

	    return c1.sort() > c2.sort() ? 1 : 0;
	}
    });

    /**
     * Temp Bean Map [已实例]
     */
    private static Map<String, Object> beanTempMap = new ConcurrentHashMap<String, Object>();

    /**
     * BeanMap[已实例,最终的容器组件]
     */
    private static final Map<String, Object> beanIocMap = new ConcurrentHashMap<String, Object>();

    static {
	String[] scanPkg = FormatUtil.toStringTrim((AppConstant.CONFIG.AppScanPKG.getValue() + ";" + AppConstant.CONFIG.AppJwebPKG.getValue())).split(";");
	for (String pkg : scanPkg) {
	    beanSet.addAll(InstanceFactory.getClassScanner().getListByAnnotation(pkg, Component.class, true));
	}
	logger.info("\tPackage[{}]：{}", beanSet.size(), scanPkg);
	addAround();
    }

    public static void setBean(Annotation anno, Class<?> cls, Object obj) {
	beanIocMap.put(SecurityUtil.Encrypt(anno.toString() + cls.toString(), encName), obj);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(Annotation anno, Class<T> cls) {
	return (T) beanIocMap.get(SecurityUtil.Encrypt(anno.toString() + cls.toString(), encName));
    }

    /**
     * 设置 Bean 实例
     */
    public static void setBean(Class<?> cls, Object obj) {
	beanIocMap.put(SecurityUtil.Encrypt(cls.toString(), encName), obj);
    }

    /**
     * 获取 Bean 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> cls) {
	return (T) beanIocMap.get(SecurityUtil.Encrypt(cls.toString(), encName));
    }

    /**
     * 设置临时 Bean 实例
     */
    public static void setTempBean(Class<?> cls, Object obj) {
	beanTempMap.put(SecurityUtil.Encrypt(cls.toString(), encName), obj);
    }

    /**
     * 获取临时 Bean 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getTempBean(Class<T> cls) {
	return (T) beanTempMap.get(SecurityUtil.Encrypt(cls.toString(), encName));
    }

    /**
     * 清空 Bean 缓存
     */
    public static void clearCache() {
	beanTempMap.clear();
	beanSet.clear();
    }

    private static void addAround() {
	// ==附加 环绕
	for (Class<?> cls : beanSet) {
	    Component comp = cls.getAnnotation(Component.class);
	    if (comp != null && (!FormatUtil.isEmpty(comp.initMethod()) || !FormatUtil.isEmpty(comp.destroyMethod()))) {
		BeanHandle.beanAround.add(cls);
		logger.info("\t[BeanAround]:" + cls.getName());
	    }
	}
    }

}
